/*-------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 1991-2007 OpenCFD Ltd.
     \\/     M anipulation  |
-----------------------------------------------------------------------------

Application:
    showDisplacement

Description:
    Utility to plot in paraFoam the structural deformation of an aero-elastic 
    wing using the data structures generated by the CAE3DToolbox to move the 
    mesh points

Remark:
    A displacement amplification factor can be specified with the option -amp
    For the mesh motion solver to work the following files are necessary:
    - cellDisplacement and pointDisplacement fields must be present in each 
      time folder (created by AeroFoam.CAE3D)
    - dynamicMeshDict file in constant folder, with the specification of the
      mesh movement algorithm options, for example:
      dynamicFvMesh dynamicMotionSolverFvMesh;   
      motionSolverLibs ("libfvMotionSolvers.so");
      solver displacementLaplacian;
      diffusivity  uniform;
    - fvSchemes file in system directory with the following laplacian scheme:
      laplacianSchemes
      {
          default none;
          laplacian(diffusivity,cellDisplacement) Gauss linear uncorrected;
      }  
    - fvSolution file in system directory with the following mesh solver:
      cellDisplacement PCG
      {
          preconditioner   DIC;
          tolerance        1e-08;
          relTol           0;
      };
    
Authors:    
    Giulio Romanelli, Elisa Serioli, (C) 2007-2008
    giulio.romanelli@gmail.com, elisa.serioli@gmail.com
    
Known bugs:
    - a warning is print complaining about overloading library. How to erase?    
      It does not affect execution.

\*---------------------------------------------------------------------------*/

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // System include

#   include "fvCFD.H"
#   include "motionSolver.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

int main(int argc, char *argv[])
{

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // System include

argList::validOptions.insert("amp", "amp");
#   include "setRootCase.H"
#   include "createTime.H"
#   include "createMesh.H" 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 

    // Variables definition
    label i, startTime, endTime;
    scalar ampFactor;
    
    // Read amplification factor
    ampFactor = 1.0;
    if (args.options().found("amp"))
    {
        ampFactor = readScalar( IStringStream( args.options()["amp"] )( ) );
        Info << "Displacement amplification factor = " << ampFactor << nl;
    }
    
    // Get times list and set startTime
    instantList Times = runTime.times();
    startTime = 1;
    endTime   = Times.size();
    runTime.setTime(Times[startTime], startTime);
     
    //--------------------------------------------------------------------------     
    // Loop on times list  
    //--------------------------------------------------------------------------
    for (i = startTime; i < endTime; i++)
    {
        // Choose time
        runTime.setTime(Times[i], i);
        Info << "\nTime = " << runTime.timeName() << nl;
                
        //----------------------------------------------------------------------
        // Read CellDisplacement, create backup and apply amplification factor
        //----------------------------------------------------------------------
        // Read cellDisplacement
        volVectorField cellDisplacement
        (
            IOobject
            (
                 "cellDisplacement",
                 runTime.timeName(),
                 mesh,
                 IOobject::MUST_READ,
                 IOobject::AUTO_WRITE
            ),
            mesh
        );
        // Backup
        volVectorField Displacement
        (
            IOobject
            (
                 "Displacement",
                 runTime.timeName(),
                 mesh,
                 IOobject::NO_READ,
                 IOobject::AUTO_WRITE
            ),
            cellDisplacement
        );
        // Apply amplification factor
        forAll( cellDisplacement.boundaryField(), iPatch )
        {
            forAll( cellDisplacement.boundaryField()[iPatch], ii )
            {
                cellDisplacement.boundaryFieldRef()[iPatch][ii] = cellDisplacement.boundaryField()[iPatch][ii]*ampFactor;
            }    
        }
        Displacement.write();
        cellDisplacement.write();
        
        //----------------------------------------------------------------------
        // Move points and update mesh structures 
        //---------------------------------------------------------------------- 
        // How to remove the warning?
        autoPtr<Foam::motionSolver> motionPtr = motionSolver::New(mesh);   
        mesh.movePoints(motionPtr->newPoints());
        mesh.write();  
    }

    // Return
    return(0);
}

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
